package com.bank.user.service.impl;

import com.bank.common.commonUtil.AuthContextHolderUtil;
import com.bank.common.exceptionUtil.CustomedException;
import com.bank.common.resultUtil.ResultCodeEnum;
import com.bank.common.stringUtil.JwtUtils;
import com.bank.common.stringUtil.UUIDUtils;
import com.bank.model.entity.*;
import com.bank.model.enums.RoleEnum;
import com.bank.model.vo.login.LoginVo;
import com.bank.model.vo.login.PersonalInfoVo;
import com.bank.model.vo.login.RegisterVo;
import com.bank.model.vo.login.UpdatePasswordVo;
import com.bank.model.vo.user.MainpageVo;
import com.bank.model.vo.user.UserBasicInfoVo;
import com.bank.model.vo.user.UserVo;
import com.bank.user.service.FileService;
import com.bank.user.service.RoleService;
import com.bank.user.util.EntityFactory;
import com.bank.user.util.MapperFactory;
import com.bank.user.service.UserService;
import com.bank.user.util.ServiceFactory;
import com.bank.user.util.VoFactory;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.*;

/**
 * @author Cejay1314
 * @version 1.0
 * @create 2023/3/22 11:05
 */

@Service
public class UserServiceImpl implements UserService {
    @Autowired
    MapperFactory mapperFactory;
    @Autowired
    EntityFactory entityFactory;
    @Autowired
    VoFactory voFactory;
    @Autowired
    ServiceFactory serviceFactory;

    @Override
    public Map<String, String> login(LoginVo loginVo) {
//        analyse the user
        QueryWrapper<User> queryWrapper = new QueryWrapper<User>();
        queryWrapper.eq("phone_number", loginVo.getUsername());
        User loginData = mapperFactory.getUserMapper().selectOne(queryWrapper);
        if (loginData == null) {
            throw new CustomedException(ResultCodeEnum.ROLE_NONEXIST);
        }
        if (!loginData.getPassword().equals(loginVo.getPassword())) {
            throw new CustomedException(ResultCodeEnum.PASSWORD_WRONG);
        }
//        analyse the role
        UserRole userRole = serviceFactory.getUserRoleService().queryByUserId(loginData.getId());
        if (userRole == null) {
            throw new CustomedException(ResultCodeEnum.ROLE_FAILED);
        }
        Role role = mapperFactory.getRoleMapper().selectById(userRole.getRoleId());

//        package the data
        Map<Object, Object> dataMap = new HashMap<>();
        dataMap.put("userId", loginData.getId().toString());
        dataMap.put("userName", loginData.getUsername());
        dataMap.put("phoneNumber", loginData.getId().toString());
        dataMap.put("role", role.getName());
//        加入taoken信息
        dataMap.put("state", UUIDUtils.getUUID());
//        加入登录时间信息,为了让我们的token发生失效效果
        dataMap.put("time", new Date().toString());
//        dataMap.put("userId",loginData.getId().toString());
//        dataMap.put("userId",loginData.getId().toString());

        String token = JwtUtils.createToken(dataMap);
//        response.addCookie(new Cookie("electronicBankToken",token));

        Map<String, String> res = new HashMap<>();
        res.put("token", token);
        res.put("role", role.getName());
        return res;
    }

    @Override
    public void register(RegisterVo registerVo) {
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("phone_number", registerVo.getPhoneNumber());
        if (query(registerVo.getPhoneNumber()) != null) {
            throw new CustomedException(ResultCodeEnum.USER_EXIST);
        }
        User user = entityFactory.getUser(registerVo);
        if (mapperFactory.getUserMapper().insert(user) <= 0) {
            throw new CustomedException(ResultCodeEnum.FAIL);
        }
        UserRole userRole = entityFactory.getUserRole(RoleEnum.User.getCode(), query(user.getPhoneNumber()).getId());
        mapperFactory.getUserRoleMapper().insert(userRole);
    }

    @Override
    public User query(String phoneNumber) {
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("phone_number", phoneNumber);
        User user = mapperFactory.getUserMapper().selectOne(queryWrapper);
        return user;
    }

    @Override
    public void updatePassword(UpdatePasswordVo updatePasswordVo, HttpServletRequest httpServletRequest) {
//        判断权限是否足够
        String role = AuthContextHolderUtil.getUserRole(httpServletRequest);
        if (!(role.equals(RoleEnum.SuperAdmin.getMessage()) ||
                AuthContextHolderUtil.getUserPhoneNumber(httpServletRequest).equals(updatePasswordVo.getPhoneNumber()))) {
            throw new CustomedException(ResultCodeEnum.ROLE_INSUFFICIENT_PERMISSIONS);
        }
//        修改密码
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.select("phone_number", updatePasswordVo.getPhoneNumber());
        User user = mapperFactory.getUserMapper().selectOne(queryWrapper);
        if (user == null) {
            throw new CustomedException(ResultCodeEnum.USER_NONEXIST);
        }
        user.setPassword(updatePasswordVo.getNewPassword());
        if (mapperFactory.getUserMapper().updateById(user) < 1) {
            throw new CustomedException(ResultCodeEnum.FAIL);
        }
    }

    @Override
    public void updateInfo(PersonalInfoVo personalInfoVo, HttpServletResponse response) {

    }


    //    查询个人信息
    @Override
    public PersonalInfoVo queryInfo(long id) {
        User user = mapperFactory.getUserMapper().selectById(id);
//        analyse the role
        UserRole userRole = mapperFactory.getUserRoleMapper().selectById(user.getId());
        if (userRole == null) {
            throw new CustomedException(ResultCodeEnum.ROLE_FAILED);
        }
        Role role = mapperFactory.getRoleMapper().selectById(userRole.getRoleId());

//        封装用户信息
        PersonalInfoVo personalInfoVo = new PersonalInfoVo(user, role);
        return personalInfoVo;
    }


    //    查询首页信息
    @Override
    public MainpageVo queryMainpageVo(HttpServletRequest httpServletRequest) {
//        query user info
        long userId = AuthContextHolderUtil.getUserId(httpServletRequest);
//        User user = mapperFactory.getUserMapper().selectById(userId);
        PersonalInfoVo personalInfoVo = queryInfo(userId);

//        query accounts info
        QueryWrapper<UserAccount> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("user_id", userId);
        List<UserAccount> userAccounts = mapperFactory.getUserAccountMapper().selectList(queryWrapper);
        List<String> accountIds = new ArrayList<>();
        for (UserAccount item : userAccounts) {
            accountIds.add(item.getAccountId());
        }
        QueryWrapper<Account> queryWrapper1 = new QueryWrapper<>();
        queryWrapper1.in("account_id", accountIds);
        List<Account> accounts = mapperFactory.getAccountMapper().selectList(queryWrapper1);


        MainpageVo mainpageVo = voFactory.getMainpageVo(personalInfoVo, accounts);
        return mainpageVo;
    }

    @Override
    public void logout(HttpServletRequest request) {
        String token = AuthContextHolderUtil.getToken(request);
        if (token == null) {
            throw new CustomedException(ResultCodeEnum.LOGIN_NOT);
        }

//        String userId = JwtUtils.getUserInfo(token).get("userId").toString();
//        if (!redisUtil.hasKey(userId)) {
//            throw new CustomedException(ResultCodeEnum.LOGIN_NOT);
//        }
//        String verify = redisUtil.get(userId).toString();
//        if (!verify.equals(token)) {
//            throw new CustomedException(ResultCodeEnum.LOGIN_OVERDUE);
//        }
//        redisUtil.del(userId);
    }


    //    删除账号
    @Override
    public void delUser(long userId) {

    }

    //    变更用户身份
    @Override
    public void updateRole(long userId, String roleName) {
        QueryWrapper<UserRole> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("userId", userId);
        if (mapperFactory.getUserRoleMapper().delete(queryWrapper) < 1) {
            throw new CustomedException(ResultCodeEnum.FAIL);
        }

        QueryWrapper<Role> queryWrapper1 = new QueryWrapper<>();
        queryWrapper.eq("name", roleName);
        Role role = mapperFactory.getRoleMapper().selectOne(queryWrapper1);

        UserRole userRole = entityFactory.getUserRole(entityFactory.getRole(roleName).getId(), userId);
        if (mapperFactory.getUserRoleMapper().insert(userRole) < 1) {
            throw new CustomedException(ResultCodeEnum.FAIL);
        }
    }

    @Override
    public List<User> getUsers(String roleName) {
        Long roleId = entityFactory.getRolesMap().get(roleName).getId();
        QueryWrapper<UserRole> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("role_id", roleId);
        List<UserRole> userRoles = mapperFactory.getUserRoleMapper().selectList(queryWrapper);
        List<User> users = new ArrayList<>();
        for (UserRole userRole : userRoles) {
            users.add(mapperFactory.getUserMapper().selectById(userRole.getUserId()));
        }
        return users;
    }

    @Override
    public List<User> queryUsers() {
        List<User> users = mapperFactory.getUserMapper().selectBatchIds(null);
        return users;
    }

    @Override
    public User queryUser(Long id) {
        return mapperFactory.getUserMapper().selectById(id);
    }

    @Override
    public UserBasicInfoVo queryUserBasicInfoVo(Long userId) {
        User user = mapperFactory.getUserMapper().selectById(userId);
        UserBasicInfoVo userBasicInfoVo = voFactory.getUserBasicInfoVo(user);
        return userBasicInfoVo;
    }

    @Override
    public void addUsers(List<UserVo> userVos) {
        for (UserVo userVo : userVos) {
            User user = entityFactory.getUser(userVo);
            mapperFactory.getUserMapper().insert(user);
            Role role = serviceFactory.getRoleService().queryRole(userVo.getRoleName());
            UserRole userRole = entityFactory.getUserRole(role.getId(),user.getId());
            mapperFactory.getUserRoleMapper().insert(userRole);
        }
    }

    @Override
    public void addUsers(MultipartFile multipartFile) throws IOException {
        List<UserVo> userVos = serviceFactory.getFileService().readUserFromExcel(multipartFile);
        addUsers(userVos);
    }

}
